package controllers

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"sort"
	"strconv"
	"sync/atomic"
	"time"

	"github.com/golang/glog"
	"github.com/gorilla/websocket"

	"display/apiserver/pkg/config"
)

const SecondTime = 1000

type WsController struct {
}

var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

var connectNums int64 = 0

func (c WsController) Get(w http.ResponseWriter, r *http.Request) {
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte("failed upgrade request"))
		glog.Errorf("failed upgrade request, err: %v", err)
		return
	}
	defer ws.Close()

	atomic.AddInt64(&connectNums, 1)
	defer atomic.AddInt64(&connectNums, -1)
	glog.Infof("Get websocket from: %s", r.RemoteAddr)
	_, msg, err := ws.ReadMessage()
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(fmt.Sprintf("failed read from %v", r.RemoteAddr)))
		glog.Errorf("failed read from %v, err: %v", r.RemoteAddr, err)
		return
	}
	glog.Infof("msg: %v", string(msg))
Loop:
	for {
		files, err := getAllFile(config.GetConfig().ResultPath)
		if err != nil {
			glog.Errorf("failed read dir[%v], err: %v", config.GetConfig().ResultPath, err)
			continue
		}
		if len(files) == 0 {
			continue
		}
		nowTime := time.Now().UnixNano() / 1e6
		for _, file := range files {
			//glog.Infof("start to handle %v", file)
			timeStamp := getTimestampFromFile(file)
			if nowTime - timeStamp > 3*SecondTime {
				glog.Warningf("%v timestamp is too old, delete it.", file)
				err = os.Remove(file)
				if err != nil {
					glog.Errorf("failed remove file[%v], err: %v", file, err)
				}
				continue
			}

			result, err := ioutil.ReadFile(file)
			if err != nil {
				glog.Errorf("failed read file[%v], err: %v", file, err)
				continue
			}
			if len(result) == 0 {
				continue
			}
			err = ws.WriteMessage(1, result)
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				w.Write([]byte(fmt.Sprintf("failed read from %v", r.RemoteAddr)))
				glog.Errorf("failed write to websocket for %v, err: %v", r.RemoteAddr, err)
				break Loop
			}
			err = os.Remove(file)
			if err != nil {
				glog.Errorf("failed remove file[%v], err: %v", file, err)
				continue
			}
		}
	}
}

func getAllFile(basePath string) ([]string, error) {
	allFileNames := []string{}
	rd, err := ioutil.ReadDir(basePath)
	if err != nil {
		return allFileNames, err
	}
	for _, fi := range rd {
		if fi.IsDir() {
			continue
		}
		allFileNames = append(allFileNames, path.Join(basePath, fi.Name()))
	}
	sort.Strings(allFileNames)
	return allFileNames, nil
}

func getTimestampFromFile(filename string) int64 {
	baseName := path.Base(filename)
	filesuffix := path.Ext(filename)
	fileprefix := baseName[0:len(baseName) - len(filesuffix)]

	timestamp, err := strconv.Atoi(fileprefix)
	if err != nil {
		glog.Errorf("failed get timestamp from filename[%v], err: %v, fileprefix: %v", filename, err, fileprefix)
		return 0
	}
	return int64(timestamp)
}